package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.context.BaseContext;
import com.sky.dto.FindOrdersDTO;
import com.sky.dto.OrdersPaymentDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.BusinessException;
import com.sky.exception.extend.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.IOrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Transactional
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private WebSocketServer webSocketServer;
    @Override
    public OrderStatisticsVO getsSatistics() {
        Integer confirmed=orderMapper.getConfirmed();
        Integer deliverInProgress=orderMapper.getDeliverInProgress();
        Integer toBeConfirmed=orderMapper.getToBeConfirmed();
        OrderStatisticsVO orderStatisticsVO=new OrderStatisticsVO();
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliverInProgress(deliverInProgress);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        return orderStatisticsVO;
    }

    @Override
    public OrdersSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        //目标：生成用户订单表。订单详情表数据
        //1 根据dto里的地址id获取地址对象
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook==null){
            throw new BusinessException("地址为空!");
        }
        //2 获取用户id
        Long userId= BaseContext.getCurrentId();
        //3再获取用户购物车数据
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.list(userId);
        if(shoppingCarts.isEmpty()){
            throw new BusinessException("该微信用户的购物车为空!");
        }
        //4可以封装订单表Orders对象数据，插入数据库
        Order order = new Order();
        BeanUtils.copyProperties(ordersSubmitDTO,order);//将DTO里的数据复制到orders
        order.setNumber(UUID.randomUUID().toString());//使用UUID生成随机数
        order.setStatus(1);//设置待付款
        order.setUserId(userId);
        order.setOrderTime(LocalDateTime.now());
        order.setPayStatus(0);//设置未支付状态
        order.setPhone(addressBook.getPhone());
        order.setAddress(addressBook.getProvinceName()+addressBook.getCityName()+
                addressBook.getDistrictName()+addressBook.getDetail());
        order.setConsignee(addressBook.getConsignee());
        orderMapper.save(order);
        //5 封装订单详情表List<OrderDetail>数据 插入数据库
        List<OrderDetail> details = shoppingCarts.stream().map((item) -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(order.getId());
            BeanUtils.copyProperties(item, orderDetail);
            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailMapper.saveBatch(details);
        //6 封装VO 核心数据返回
        return OrdersSubmitVO.builder()
                .id(order.getId())
                .orderNumber(order.getNumber())
                .orderAmount(order.getAmount())
                .orderTime(order.getOrderTime())
                .build();
    }

    @Override
    public PageResult<OrdersOverVO> historyOrders(Integer page, Integer pageSize, Integer status) {
        //获取用户id
        Long userId=BaseContext.getCurrentId();
        PageHelper.startPage(page,pageSize);
        Page<Order> orderPages=orderMapper.page(status,userId);
        //获取OrderId,再查询对应的details表 最后进行封装成OrderDetails
        List<OrdersOverVO> ordersOverVOS = orderPages.stream().map((item) -> {
            OrdersOverVO ordersOverVO = new OrdersOverVO();
            BeanUtils.copyProperties(item, ordersOverVO);
            List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(item.getId());
            ordersOverVO.setOrderDetailList(orderDetails);
            return ordersOverVO;
        }).collect(Collectors.toList());
        return new PageResult<>(orderPages.getTotal(),ordersOverVOS);
    }

    /**
     * 支付成功，修改订单状态
     * @param outTradeNo
     */
    @Override
    public void paySuccess(String outTradeNo) {
        //根据订单号查询订单
       Order ordersDB= orderMapper.getByNumber(outTradeNo);

       // 根据订单id 更新订单的状态 支付方式 支付状态 结账时间
        Order order = Order.builder()
                .id(ordersDB.getId())
                .status(2)
                .payStatus(1)
                .checkoutTime(LocalDateTime.now())
                .build();
        //更新状态
        orderMapper.update(order);
        //通过webSocket向客户端推送消息
        Map<Object,Object> map=new HashMap<>();
        map.put("type",1);//1表示来单提醒 2表示催单
        map.put("orderId",order.getId());
        map.put("content","订单号："+outTradeNo);
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }

    /**
     *订单支付
     *
     *
     * @param ordersPaymentDTO
     * @return
     */
    @Override
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        //获取当前用户id
        Long userId=BaseContext.getCurrentId();
        User user=userMapper.getById(userId);
        //调用微信支付接口，生成预支付订单
        JSONObject jsonObject = weChatPayUtil.pay(
                ordersPaymentDTO.getOrderNumber(),//商户订单号
                new BigDecimal(0.01),//支付金额，前端并没有传来唯一订单号
                "苍穹外卖",//商品描述
                user.getOpenid()//微信用户的openId
        );
        if(jsonObject.getString("code")!=null && jsonObject.getString("code").equals("ORDERPAID")){
            throw new OrderBusinessException("订单已经支付");
        }
        OrderPaymentVO orderPaymentVO = jsonObject.toJavaObject(OrderPaymentVO.class);
        orderPaymentVO.setPackageStr(jsonObject.getString("package"));
        return orderPaymentVO;
    }

    @Override
    public OrdersOverVO orderDetailById(Long id) {
        //先根据id查询对应order
        Order order=orderMapper.getById(id);
        //复制在复制
        OrdersOverVO ordersOverVO=new OrdersOverVO();
        BeanUtils.copyProperties(order,ordersOverVO);
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
        ordersOverVO.setOrderDetailList(orderDetails);
        return ordersOverVO;
    }

    @Override
    public void cancel(Long id) {
        orderMapper.cancel(id,LocalDateTime.now());
    }

    @Override
    public void repetition(Long id) {
        //先查询出对的order 以及order_detail
        Order order = orderMapper.getById(id);
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
        //并把一些值赋值为空
        order.setId(null);
        order.setCheckoutTime(null);
       // order.setPayMethod(null);
        order.setCancelReason(null);
        order.setCancelTime(null);
        order.setRejectionReason(null);
        order.setEstimatedDeliveryTime(null);
        order.setDeliveryTime(null);
        //生成UUID对应的
        order.setNumber(UUID.randomUUID().toString());
        //设置status为待付款
        order.setStatus(1);
        //赋值下单时间
        order.setUserId(BaseContext.getCurrentId());
        //赋值下单时间
        order.setOrderTime(LocalDateTime.now());
        //生成未支付状态
        order.setPayStatus(0);
        orderMapper.save(order);
        orderDetails.forEach((item)->{
            item.setOrderId(order.getId());
        });
        orderDetailMapper.saveBatch(orderDetails);
    }
    @Override
    public PageResult<OrdersFindVO> conditionSearch(FindOrdersDTO findOrdersDTO) {
        //首先是一个很多属性的分页查询，而且设计多表
        PageHelper.startPage(findOrdersDTO.getPage(), findOrdersDTO.getPageSize());
        Page<Order> orderPage=orderMapper.conditionSearch(findOrdersDTO);
        //再进行封装
        List<OrdersFindVO> ordersFindVOS = orderPage.getResult().stream().map((item) -> {
            OrdersFindVO ordersFindVO = new OrdersFindVO();
            BeanUtils.copyProperties(item, ordersFindVO);
            List<String> names = orderDetailMapper.getByNamesByOrderId(item.getId());
            ordersFindVO.setOrderDishes(names.toString());
            return ordersFindVO;
        }).collect(Collectors.toList());
        return new PageResult<>(orderPage.getTotal(),ordersFindVOS);
    }

    @Override
    public OrderVO details(Long id) {
        //先查order表
        Order order = orderMapper.getById(id);
        //创建orderVO对象 进行复制
        OrderVO orderVO=new OrderVO();
        BeanUtils.copyProperties(order,orderVO);
        //在orderDetail表中查询orderDetailLists
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
        if (orderDetails.isEmpty()){
            throw new BusinessException("该订单出现了问题暂未有订单详细数据,建议拒单!");
        }
        orderVO.setOrderDetailList(orderDetails);
        //再查询具体的菜品
        List<String> names = orderDetailMapper.getByNamesByOrderId(id);
        orderVO.setOrderDishes(names.toString());
        return orderVO;
    }

    @Override
    public void confirm(Long id) {
        //直接修改数据库里的值就好
        orderMapper.confirme(id);
    }

    @Override
    public void delivery(Long id) {
        orderMapper.delivery(id);
    }

    @Override
    public void complete(Long id) {
        orderMapper.complete(id);
    }

    @Override
    public void reminder(Long id) {
        Order order = orderMapper.getById(id);
        //校验订单是否存在
        if (order==null){
            throw new OrderBusinessException("该订单状态出现了错误");
        }
        Map<Object,Object> map=new HashMap<>();
        map.put("type",2);
        map.put("orderId",order.getId());
        map.put("content","订单号："+order.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }
}
